package http_proxy_router

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"go_gateway/cmd"
	"go_gateway/middleware"
	"go_gateway/reverse_proxy/load_balance"

	"github.com/gin-gonic/gin"
	"github.com/urfave/cli/v2"
)

var (
	HttpSrvHandler  *http.Server
	HttpsSrvHandler *http.Server
)

func Run(ctx *cli.Context) error {
	name := ctx.String("name")
	addr := ctx.String("addr")
	urls := ctx.StringSlice("urls")
	lb := &load_balance.RoundRobinBalance{}
	for _, url := range urls {
		lb.Add(url)
	}

	HttpServerRun(name, addr, lb)
	return nil
}

func init() {
	command := &cli.Command{
		Name:  "http_reverse_proxy",
		Usage: fmt.Sprintf("%s http_reverse_proxy", os.Args[0]),
		Action: func(ctx *cli.Context) error {
			return Run(ctx)
		},
		Flags: []cli.Flag{
			&cli.StringFlag{
				Name:    "name",
				Aliases: []string{"n"},
				Value:   "http_reverse_proxy",
			},
			&cli.StringSliceFlag{
				Name:    "urls",
				Aliases: []string{"us"},
				Value:   cli.NewStringSlice("http://127.0.0.1:9000"),
			},
			&cli.StringFlag{
				Name:    "addr",
				Aliases: []string{"a"},
				Value:   ":8090",
			},
		},
	}
	cmd.Register(command)
}

func HttpServerRun(name string, addr string, lb load_balance.LoadBalance) {
	gin.SetMode("debug")
	r := InitRouter(lb, middleware.RecoveryMiddleware())
	HttpSrvHandler = &http.Server{
		Addr:           addr,
		Handler:        r,
		ReadTimeout:    time.Duration(60) * time.Second,
		WriteTimeout:   time.Duration(60) * time.Second,
		MaxHeaderBytes: 1 << uint(20),
	}
	log.Printf(" [INFO] http_proxy_run %s\n", addr)
	if err := HttpSrvHandler.ListenAndServe(); err != nil && err != http.ErrServerClosed {
		log.Fatalf(" [ERROR] http_proxy_run %s err:%v\n", addr, err)
	}
}

// func HttpsServerRun() {
// 	gin.SetMode(lib.GetStringConf("proxy.base.debug_mode"))
// 	r := InitRouter(middleware.RecoveryMiddleware(),
// 		middleware.RequestLog())
// 	HttpsSrvHandler = &http.Server{
// 		Addr:           lib.GetStringConf("proxy.https.addr"),
// 		Handler:        r,
// 		ReadTimeout:    time.Duration(lib.GetIntConf("proxy.https.read_timeout")) * time.Second,
// 		WriteTimeout:   time.Duration(lib.GetIntConf("proxy.https.write_timeout")) * time.Second,
// 		MaxHeaderBytes: 1 << uint(lib.GetIntConf("proxy.https.max_header_bytes")),
// 	}
// 	log.Printf(" [INFO] https_proxy_run %s\n", lib.GetStringConf("proxy.https.addr"))
// 	//todo 以下命令只在编译机有效，如果是交叉编译情况下需要单独设置路径
// 	//if err := HttpsSrvHandler.ListenAndServeTLS(cert_file.Path("server.crt"), cert_file.Path("server.key")); err != nil && err!=http.ErrServerClosed {
// 	if err := HttpsSrvHandler.ListenAndServeTLS("./cert_file/server.crt", "./cert_file/server.key"); err != nil && err != http.ErrServerClosed {
// 		log.Fatalf(" [ERROR] https_proxy_run %s err:%v\n", lib.GetStringConf("proxy.https.addr"), err)
// 	}
// }

func HttpServerStop() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	if err := HttpSrvHandler.Shutdown(ctx); err != nil {
		log.Printf(" [ERROR] http_proxy_stop err:%v\n", err)
	}
	log.Printf(" [INFO] http_proxy_stop %v stopped\n", "")
}

// func HttpsServerStop() {
// 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// 	defer cancel()
// 	if err := HttpsSrvHandler.Shutdown(ctx); err != nil {
// 		log.Fatalf(" [ERROR] https_proxy_stop err:%v\n", err)
// 	}
// 	log.Printf(" [INFO] https_proxy_stop %v stopped\n", lib.GetStringConf("proxy.https.addr"))
// }
